package com.woniu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniu.client.AccountClient;
import com.woniu.client.OrderClient;
import com.woniu.client.VenueClient;
import com.woniu.commons.exception.VenueRuntimeException;
import com.woniu.commons.exception.YogaException;
import com.woniu.commons.model.RedisKey;
import com.woniu.commons.model.Result;
import com.woniu.commons.model.StateData;
import com.woniu.dao.mapper.YClassTypeMapper;
import com.woniu.dao.mapper.YLeagueClassMapper;
import com.woniu.dao.mapper.YLeagueWorkforceMapper;
import com.woniu.dao.mapper.YUserLeagueClassMarginMapper;
import com.woniu.model.AddLeagueClassDetailForm;
import com.woniu.model.YCoach;
import com.woniu.model.model.*;
import com.woniu.model.dto.LeagueClassDto;
import com.woniu.model.dto.LeagueWorkforceDto;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.model.param.AddLeagueClassForceParam;
import com.woniu.model.param.LoadLeagueClassForceParam;
import com.woniu.service.YLeagueWorkforceService;
import io.seata.spring.annotation.GlobalTransactional;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.format.DateTimeFormatters;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 吴彦祖
 * @since 2024年05月23日
 */
@Service
public class YLeagueWorkforceServiceImpl extends ServiceImpl<YLeagueWorkforceMapper, YLeagueWorkforce> implements YLeagueWorkforceService {

    @Resource
    private YLeagueWorkforceMapper leagueWorkforceMapper;
    @Autowired
    private YLeagueClassMapper leagueClassMapper;
    @Resource
    private OrderClient orderClient;
    @Resource
    private YUserLeagueClassMarginMapper userLeagueClassMarginMapper;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private AccountClient accountClient;
    @Resource
    private YClassTypeMapper classTypeMapper;
    @Resource
    private VenueClient venueClient;

    /**
     * 查询时段团课列表
     *
     * @param param
     * @return
     */
    @Override
    public List<YLeagueWorkforce> loadLeagueClassForceByVenueId(LoadLeagueClassForceParam param) {
        QueryWrapper<YLeagueWorkforce> wrapper = new QueryWrapper<>();
        wrapper.gt("start_time", param.getStartTime()).lt("start_time", param.getEndTime()).eq("venue_id", param.getVenueId());
        wrapper.or().gt("end_time", param.getStartTime());
        List<YLeagueWorkforce> list = leagueWorkforceMapper.selectList(wrapper);
        if (list.size() == 0) {
            throw new YogaException(3101, "该时间段无课程");
        }
        return list;
    }

    /**
     * 新增团课排班
     *
     * @param param
     * @return
     */
    @Override
    @GlobalTransactional(rollbackFor = Throwable.class)
    public void addLeagueClassForce(AddLeagueClassForceParam param) throws Exception {
        RLock fairLock = redissonClient.getFairLock(RedisKey.leagueClassWorkforceClassIdLock(param.getLeagueClassId()));
        RLock lock = redissonClient.getMultiLock(fairLock);
        Integer i = 0;
        try {
            boolean success = lock.tryLock(20, TimeUnit.SECONDS);
//            System.out.println(success);
            if (success) {
//                System.out.println("??????????????????");
                YLeagueClass leagueClass = leagueClassMapper.selectOne(new QueryWrapper<YLeagueClass>().eq("league_class_id",param.getLeagueClassId()));
                System.out.println(leagueClass);
                List<YLeagueWorkforce> list = baseMapper.selectList(new QueryWrapper<YLeagueWorkforce>().eq("league_class_id", param.getLeagueClassId()));
                System.out.println(list);
                if (list.size() == leagueClass.getClassNum()){
                    throw new YogaException(3501,"排课数量超出课程上限");
                }
                System.out.println("??????????????????");
                if (leagueClass == null) {
                    throw new YogaException(3015, "团课信息不存在");
                }
                if (!leagueClass.getVenueId().equals(param.getVenueId())) {
                    throw new YogaException(3016, "该场馆无此团课信息");
                }

                LocalDateTime startTime = LocalDateTime.parse(param.getStartTime(),DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                if (startTime.isBefore(LocalDateTime.now())){
                    throw new YogaException(3503,"只能排班未来的时间");
                }

                LocalDateTime endTime = LocalDateTime.parse(param.getEndTime(),DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                System.out.println(endTime);
                if (startTime.isAfter(endTime)){
                    throw new YogaException(3504,"开始时间不能晚于结束时间");
                }
                Duration duration = Duration.between(endTime, startTime);
                long minutes = - duration.toMinutes();
                System.out.println(minutes);
                if (minutes < leagueClass.getMinute()) {
                    throw new YogaException(3410, "排课时间少于单节课时长");
                }
//                endTime.minus(startTime);


                System.out.println("changestate");
                YLeagueWorkforce leagueWorkforce = BeanUtil.toBean(param, YLeagueWorkforce.class);
                leagueWorkforce.setLeagueClassWorkforceState(StateData.LEAGUE_WORKFORCE_STATE_NOT_OK);

                System.out.println("insertworkforce");
                leagueWorkforceMapper.insert(leagueWorkforce);
                YLeagueWorkforce yLeagueWorkforce = leagueWorkforceMapper.selectOne(new QueryWrapper<YLeagueWorkforce>().eq("league_class_id", param.getLeagueClassId()).eq("start_time", param.getStartTime()).eq("league_class_workforce_state", StateData.LEAGUE_WORKFORCE_STATE_NOT_OK));


                List<YUserLeagueClassMargin> userLeagueClassMargins = userLeagueClassMarginMapper.selectList(new QueryWrapper<YUserLeagueClassMargin>().eq("personal_class_id", param.getLeagueClassId()).ne("margin_num", 0));


                System.out.println("client");
                AddLeagueClassDetailForm addLeagueClassDetailForm = new AddLeagueClassDetailForm(leagueWorkforce.getStartTime(), leagueWorkforce.getEndTime(), param.getCoachId(), userLeagueClassMargins, param.getLeagueClassId(), yLeagueWorkforce.getId());
                orderClient.addLeagueClassDetail(addLeagueClassDetailForm);

            } else {
                throw new RuntimeException("服务器繁忙");
            }

        } catch (Exception e) {
            throw new Exception(e);
        } finally {
            //释放锁
            lock.unlock();
        }


    }

    /**
     * 查询该场馆此时段可以排班的课程
     *
     * @return
     */
    @Override
    public List<LeagueClassDto> loadLeagueClassForceWhichAllow(LoadLeagueClassForceParam param) {
        QueryWrapper<YLeagueWorkforce> wrapper = new QueryWrapper<>();
        wrapper.eq("venue_id", param.getVenueId());
        wrapper.lt("start_time", param.getEndTime()).gt("end_time", param.getEndTime());

        wrapper.or();
        wrapper.eq("venue_id", param.getVenueId());
        wrapper.gt("end_time", param.getStartTime()).lt("start_time", param.getStartTime());

        wrapper.or();
        wrapper.eq("venue_id", param.getVenueId());
        wrapper.lt("end_time", param.getEndTime()).gt("start_time", param.getStartTime());

        //有冲突的课程
        List<YLeagueWorkforce> list = leagueWorkforceMapper.selectList(wrapper);

        Set<Integer> leagueClassClassroom = list.stream().map(o -> o.getClassroomId()).collect(Collectors.toSet());

        List<Integer> leagueClassIds = list.stream().map(o -> o.getLeagueClassId()).collect(Collectors.toList());



        QueryWrapper<YLeagueClass> leagueClassQueryWrapper = new QueryWrapper<>();
        if (leagueClassIds.size()!=0){
            leagueClassQueryWrapper.notIn("league_class_id", leagueClassIds);
        }
        leagueClassQueryWrapper.eq("venue_id", param.getVenueId()).ne("league_class_state", StateData.LEAGUE_CLASS_STATE_DISABLED).ne("league_class_state",StateData.LEAGUE_CLASS_STATE_DISABLED);

        List<YLeagueClass> leagueClasses = leagueClassMapper.selectList(leagueClassQueryWrapper);
        List<YLeagueClass> realList = new ArrayList<>();
        for (YLeagueClass l : leagueClasses
        ) {
            boolean a = true;
            for (Integer classroom : leagueClassClassroom
            ) {
                if (l.getClassroomId().equals(classroom)) {
                    a = false;
                    break;
                }

            }
            if (a) {
                realList.add(l);
            }
        }

        ArrayList<LeagueClassDto> leagueClassDtos = new ArrayList<>();
        for (YLeagueClass l:realList
             ) {
            List<YLeagueWorkforce> leagueWorkforces = baseMapper.selectList(new QueryWrapper<YLeagueWorkforce>().eq("league_class_id", l.getLeagueClassId()));
            if (leagueWorkforces.size()>= l.getClassNum()){
                break;
            }
            LeagueClassDto leagueClassDto = BeanUtil.toBean(l, LeagueClassDto.class);
            leagueClassDto.setCoachName(accountClient.byId(l.getCoachId()).getData().getCoachNickName());
            leagueClassDto.setClassTypeName( classTypeMapper.selectById(l.getClassTypeId()).getClassTypeName());
            leagueClassDtos.add(leagueClassDto);

        }


        return leagueClassDtos;
    }

    @Override
    public Integer finishLeagueClassForce(Integer coachId, Integer id) {
        YLeagueWorkforce leagueWorkforce = baseMapper.selectById(id);
        if (leagueWorkforce == null) {
            throw new YogaException(3107, "不存在该团课排班信息");
        }
        if (!leagueWorkforce.getCoachId().equals(coachId)) {
            throw new YogaException(3108, "该教练无权处理该团课");
        }
        if (LocalDateTime.now().isBefore(leagueWorkforce.getEndTime())) {
            throw new YogaException(3109, "还未到结束时间，请勿提前结束");
        }
        if (!leagueWorkforce.getLeagueClassWorkforceState().equals(StateData.LEAGUE_WORKFORCE_STATE_NOT_OK)) {
            throw new YogaException(3110, "团课状态异常");
        }
        leagueWorkforce.setLeagueClassWorkforceState(StateData.LEAGUE_CLASS_STATE_COMPLETE);
        int i = baseMapper.updateById(leagueWorkforce);

        List<YUserLeagueClassMargin> userLeagueClassMargins = userLeagueClassMarginMapper.selectList(new QueryWrapper<YUserLeagueClassMargin>().eq("personal_class_id", leagueWorkforce.getLeagueClassId()).ne("margin_num", 0));
        for (YUserLeagueClassMargin u : userLeagueClassMargins
        ) {
            u.setMarginNum(u.getMarginNum() - 1);
            userLeagueClassMarginMapper.updateById(u);
        }

        orderClient.finishLeagueClassDetail(leagueWorkforce.getId());

        return i;
    }

    @Override
    public Integer cancelLeagueClassForce(Integer coachId, Integer id) {
        YLeagueWorkforce leagueWorkforce = baseMapper.selectById(id);
        if (leagueWorkforce == null) {
            throw new YogaException(3107, "不存在该团课排班信息");
        }
        if (!leagueWorkforce.getCoachId().equals(coachId)) {
            throw new YogaException(3108, "该教练无权处理该团课");
        }
        if (!leagueWorkforce.getLeagueClassWorkforceState().equals(StateData.LEAGUE_WORKFORCE_STATE_NOT_OK)) {
            throw new YogaException(3110, "团课状态异常");
        }

        leagueWorkforce.setLeagueClassWorkforceState(StateData.LEAGUE_WORKFORCE_STATE_CANCEL);
        int i = baseMapper.updateById(leagueWorkforce);


        orderClient.cancelLeagueClassDetail(leagueWorkforce.getLeagueClassId());

        return i;
    }

    /**
     * 根据课程id查询排班信息
     *
     * @param courseId
     * @return
     */
    @Override
    public List<YLeagueWorkforce> loadLeagueWorkforceByClassId(Integer courseId) {
        List<YLeagueWorkforce> list = baseMapper.selectList(new QueryWrapper<YLeagueWorkforce>().eq("league_class_id", courseId).eq("league_class_workforce_state", StateData.LEAGUE_WORKFORCE_STATE_NOT_OK));


        return list;
    }

    /**
     * 根据教练id查询未完成的团课
     * @param coachId
     * @return
     */
    @Override
    public List<LeagueWorkforceDto> loadLeagueWorkforceByCoach(Integer coachId,String className) {
        QueryWrapper<YLeagueWorkforce> eq = new QueryWrapper<YLeagueWorkforce>().eq("coach_id", coachId).eq("league_class_workforce_state", StateData.LEAGUE_WORKFORCE_STATE_NOT_OK);

        if (className!=null){
            List<YLeagueClass> leagueClassList = leagueClassMapper.selectList(new QueryWrapper<YLeagueClass>().eq("league_class_name", className));
            eq.in("league_class_id",leagueClassList.stream().map(o->o.getLeagueClassId()));
        }

        List<YLeagueWorkforce> list = baseMapper.selectList(eq);
        ArrayList<LeagueWorkforceDto> dtos = new ArrayList<>();
        for (YLeagueWorkforce l:list
             ) {
            LeagueWorkforceDto dto = BeanUtil.toBean(l, LeagueWorkforceDto.class);
            dto.setVenueBase(BeanUtil.toBean(venueClient.loadVenueBaseById(l.getVenueId()).getData(),YVenueBase.class));
            dto.setVenueClassroom(BeanUtil.toBean( venueClient.loadClassroomById(l.getClassroomId()).getData(), YVenueClassroom.class));
            dto.setLeagueClass( leagueClassMapper.selectOne(new QueryWrapper<YLeagueClass>().eq("league_class_id",l.getLeagueClassId())));
            dtos.add(dto);
        }

        return dtos;
    }
}
